﻿Imports System.ComponentModel.DataAnnotations
Imports System.Reflection
Imports System.Web.Mvc
Imports System.Globalization

Namespace Models.Validators

    ''' <summary>
    ''' Atributo para comparar con otro campo fecha si el valor del campo es mayor que el campo en comparacion
    ''' </summary>
    ''' <remarks></remarks>
    Public Class CompareDateMayorAttribute
        Inherits ValidationAttribute
        Implements IClientValidatable, IMetadataAware

        Private Property CompareProperty As String
        Private ReadOnly m_DisplayNameOther As String
        Private Const _ErrorMessage As String = "La fecha del campo '{0}' debe ser mayor que la fecha del campo '{1}'"

        ''' <summary>
        ''' Compara la fecha del campo con la fecha del campo especificado. Si la fecha del campo actual es mayor que la fecha
        ''' de la propiedad en comparacion es valido, de lo contrario regresa error
        ''' </summary>
        ''' <param name="compare">Nombre de la propiedad del modelo con el que se debe de comparar</param>
        ''' <param name="OtherPropertyDisplayName">Nombre a mostrar de la propiedad a comparar</param>
        ''' <remarks></remarks>
        Sub New(compare As String, OtherPropertyDisplayName As String)
            MyBase.New(_ErrorMessage)
            Me.CompareProperty = compare
            Me.m_DisplayNameOther = OtherPropertyDisplayName
        End Sub

        Public Overrides Function FormatErrorMessage(name As String) As String
            Return String.Format(ErrorMessageString, name, Me.m_DisplayNameOther)
        End Function

        Protected Overrides Function IsValid(value As Object, validationContext As System.ComponentModel.DataAnnotations.ValidationContext) As System.ComponentModel.DataAnnotations.ValidationResult
            Dim otherInfo As PropertyInfo = validationContext.ObjectType.GetProperty(Me.CompareProperty)
            Dim otherObj = otherInfo.GetValue(validationContext.ObjectInstance, Nothing)

            'Validacion REQUIRED
            If value Is Nothing OrElse otherObj Is Nothing Then Return Nothing
            'Validacion REGEXP
            If Not Regex.IsMatch(value.ToString, "^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](201)\d$") OrElse
               Not Regex.IsMatch(otherObj.ToString, "^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](201)\d$") Then Return Nothing

            'Recuperamos los valores de las 2 fechas que estamos comparando
            Dim otherValue, currentValue As Date

            'Validacion ISDATE
            If Not Date.TryParseExact(value.ToString, "dd/MM/yyyy", CultureInfo.GetCultureInfo("es-SV"), DateTimeStyles.None, currentValue) OrElse _
               Not Date.TryParseExact(otherObj.ToString, "dd/MM/yyyy", CultureInfo.GetCultureInfo("es-SV"), DateTimeStyles.None, otherValue) Then Return Nothing

            'El "CurrentValue" tiene que se mayor que "OtherValue" para poder validar correctamente
            If Date.Compare(otherValue, currentValue) >= 0 Then
                'Si son iguales o OtherValue es mayor entonces retornamos un error
                Return New ValidationResult(FormatErrorMessage(validationContext.DisplayName))
            End If
            Return Nothing
        End Function


        '***********************************
        '**VALIDACION DEL LADO DEL CLIENTE**
        '***********************************
        Public Function GetClientValidationRules(metadata As System.Web.Mvc.ModelMetadata, context As System.Web.Mvc.ControllerContext) As System.Collections.Generic.IEnumerable(Of System.Web.Mvc.ModelClientValidationRule) Implements System.Web.Mvc.IClientValidatable.GetClientValidationRules
            Dim var As New List(Of ModelClientValidationRule)
            Dim otherInfo = context.Controller.ViewData.Values.Select(Function(m) m.CompareProperty)
            Dim rule = New ModelClienteValidationDateMayorRule(Me.FormatErrorMessage(metadata.GetDisplayName), Me.CompareProperty)
            var.Add(rule)
            Return var.AsEnumerable
        End Function

        Public Class ModelClienteValidationDateMayorRule
            Inherits ModelClientValidationRule

            Public Sub New(errorMessage As String, NameCompareProperty As String)
                Me.ErrorMessage = errorMessage
                Me.ValidationType = "dateismayor"
                Me.ValidationParameters.Add("valuedatecompare", NameCompareProperty)
            End Sub
        End Class

        Public Sub OnMetadataCreated(metadata As System.Web.Mvc.ModelMetadata) Implements System.Web.Mvc.IMetadataAware.OnMetadataCreated
            metadata.DataTypeName = "Date"
        End Sub
    End Class

End Namespace
